<?php
declare (strict_types = 1);

namespace app\service;

use think\facade\Config;
use think\facade\Log;

class WechatService
{
    protected $appId;
    protected $appSecret;
    protected $token;
    protected $encodingAesKey;
    
    public function __construct()
    {
        $this->appId = Config::get('wechat.app_id');
        $this->appSecret = Config::get('wechat.app_secret');
        $this->token = Config::get('wechat.token');
        $this->encodingAesKey = Config::get('wechat.encoding_aes_key');
    }
    
    /**
     * 验证消息签名
     */
    public function checkSignature($signature, $timestamp, $nonce)
    {
        $tmpArr = array($this->token, $timestamp, $nonce);
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode($tmpArr);
        $tmpStr = sha1($tmpStr);
        
        return $tmpStr == $signature;
    }
    
    /**
     * 接收消息
     */
    public function receiveMessage($postData)
    {
        try {
            $xml = simplexml_load_string($postData, 'SimpleXMLElement', LIBXML_NOCDATA);
            if (!$xml) {
                throw new \Exception('Invalid XML data');
            }
            
            $msgType = strtolower($xml->MsgType);
            $fromUser = $xml->FromUserName;
            $toUser = $xml->ToUserName;
            $createTime = $xml->CreateTime;
            
            $message = [
                'type' => $msgType,
                'from' => $fromUser,
                'to' => $toUser,
                'time' => $createTime
            ];
            
            // 根据消息类型处理不同的消息
            switch ($msgType) {
                case 'text':
                    $message['content'] = $xml->Content;
                    break;
                case 'image':
                    $message['mediaId'] = $xml->MediaId;
                    $message['picUrl'] = $xml->PicUrl;
                    break;
                case 'voice':
                    $message['mediaId'] = $xml->MediaId;
                    $message['format'] = $xml->Format;
                    break;
                case 'video':
                    $message['mediaId'] = $xml->MediaId;
                    $message['thumbMediaId'] = $xml->ThumbMediaId;
                    break;
                case 'link':
                    $message['title'] = $xml->Title;
                    $message['description'] = $xml->Description;
                    $message['url'] = $xml->Url;
                    break;
                case 'event':
                    $message['event'] = strtolower($xml->Event);
                    if (isset($xml->EventKey)) {
                        $message['eventKey'] = $xml->EventKey;
                    }
                    break;
            }
            
            return $message;
        } catch (\Exception $e) {
            Log::error('Receive message error: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * 发送文本消息
     */
    public function sendTextMessage($toUser, $content)
    {
        $message = [
            'touser' => $toUser,
            'msgtype' => 'text',
            'text' => [
                'content' => $content
            ]
        ];
        
        return $this->sendMessage($message);
    }
    
    /**
     * 发送图片消息
     */
    public function sendImageMessage($toUser, $mediaId)
    {
        $message = [
            'touser' => $toUser,
            'msgtype' => 'image',
            'image' => [
                'media_id' => $mediaId
            ]
        ];
        
        return $this->sendMessage($message);
    }
    
    /**
     * 发送模板消息
     */
    public function sendTemplateMessage($toUser, $templateId, $data, $url = '', $miniprogram = [])
    {
        $message = [
            'touser' => $toUser,
            'template_id' => $templateId,
            'data' => $data
        ];
        
        if ($url) {
            $message['url'] = $url;
        }
        
        if (!empty($miniprogram)) {
            $message['miniprogram'] = $miniprogram;
        }
        
        return $this->sendMessage($message);
    }
    
    /**
     * 发送消息
     */
    protected function sendMessage($message)
    {
        try {
            $accessToken = $this->getAccessToken();
            $url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token={$accessToken}";
            
            $response = $this->httpPost($url, json_encode($message));
            $result = json_decode($response, true);
            
            if (isset($result['errcode']) && $result['errcode'] != 0) {
                Log::error('Send message error: ' . json_encode($result));
                return false;
            }
            
            return true;
        } catch (\Exception $e) {
            Log::error('Send message error: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * 获取访问令牌
     */
    protected function getAccessToken()
    {
        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->appId}&secret={$this->appSecret}";
        
        $response = $this->httpGet($url);
        $result = json_decode($response, true);
        
        if (isset($result['access_token'])) {
            return $result['access_token'];
        }
        
        throw new \Exception('Get access token failed: ' . json_encode($result));
    }
    
    /**
     * HTTP GET请求
     */
    protected function httpGet($url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }
    
    /**
     * HTTP POST请求
     */
    protected function httpPost($url, $data)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }
} 